<!--甘特图首页-->
<template>
  <div class="gantt-table">
    <!-- 头部-->
    <!-- <div class="gantt-head">
			<div class="gantt-fixed">
				<div class="gantt-head" style="padding: 5px 20px;">
					<span>时间区间:</span>
					<div style="width: 240px;">{{ _formatDate(choiceTime[0]) }} - {{ _formatDate(choiceTime[1]) }}</div>
					 <el-button type="primary" size="mini" @click="save">保存</el-button>

					<el-button type="danger" size="mini" plain @click="_hisBack">撤回({{ hisList.length }})</el-button>

					<el-button type="danger" v-if="!isDeleteMode" size="mini" plain @click="isDeleteMode = true">批量删除</el-button>
					<el-button type="danger" v-if="isDeleteMode" size="mini" plain @click="isDeleteMode = false">取消删除</el-button> 
				</div>
			</div>
		</div> -->
    <div class="gantt-box" style="height:50vh">
      <div class="left" ref="left">
        <div class="head">
          <!--    左边栏的列表头      -->
          <div class="head-box">
            <GanttRow>
              <GanttBlock class="text-line-1">班组</GanttBlock>
              <GanttBlock>产品</GanttBlock>
              <GanttBlock>产品编码</GanttBlock>
              <GanttBlock>计划数量</GanttBlock>
            </GanttRow>
          </div>
        </div>
        <!--  左边栏的列表内容      -->
        <div class="left-box" :style="{ transform: `translateY(-${transFormYValue}px)` }">
          <GanttRow v-for="(item, index) in ganttData" :key="index">
            <GanttBlock class="text-line-1">{{ item.definition }}</GanttBlock>
            <GanttBlock>{{ item.partName }}</GanttBlock>
            <GanttBlock>{{ item.partCode }}</GanttBlock>
            <GanttBlock>{{ item.orderQuantity }}</GanttBlock>
          </GanttRow>
        </div>
      </div>
      <!--    右边的内容      -->
      <div class="right" ref="right">
        <!--  时间头      -->
        <div class="head">
          <div class="head-box">
            <GanttRow :style="{ transform: `translatex(-${transFormXValue}px)` }"
              class="transition-transForm">
              <GanttTimeBlock :target-time="_formatDate(item)"
                v-for="(item, index) in choiceTimeArr" :key="index"></GanttTimeBlock>
            </GanttRow>

            <div style="width: 200px;height:60px;">备注</div>
          </div>
        </div>
        <div class="content" ref="contentGrid"  style="height:44vh">
          <div v-if="ganttData.length > 0">
            <!--      甘特图中具体的内容   -->
            <div class="gantt-grid" ref="box" @contextmenu.prevent="() => { }">
              <!--   网格状图表  -->
              <GanttRow v-for="(item, rowIndex) in ganttData" :key="rowIndex"
                :id="`ganttRow-${rowIndex}`" class="gantt-row-relative"
                :class="{ 'gantt-row-active': nowSuck === rowIndex }">
                <!-- <template>  -->
                <!-- :class="' block-type-' + times.status" -->
                <!--
                @mousedown="onMouseDown($event, item.id, rowIndex)"
                @contextmenu.prevent="onRightClick($event, item, item)"
                @click.stop="onClicked(item,rowIndex)" :title="item.partName"
                @dblclick="onDbClicked(item,rowIndex)" 
              -->
                <div :key="`times-${rowIndex}`" :style="_timeBlockStyle(item)"  @mousedown="onMouseDown($event, item.id, rowIndex)"
                  class="time-block gantt-grab gantt-grab-no" :class="' block-type-' + rowIndex">
                  {{item.partName }}
                </div>
                <!-- </template>	 -->
                <!--      block => 180  因为[this.listKey] => 60    60*3 = 180px   -->
                <GanttBlock class="time" v-for="rowIndex in choiceTimeArr.length" :key="rowIndex"
                  style="flex-shrink: 0"></GanttBlock>
                <!-- <GanttBlock style="width: 200px;"
                :style="_mergeStyle('typeName', item.partName, rowIndex, false)">
                {{ item.remark }}
              </GanttBlock> -->
              </GanttRow>
            </div>
            <!-- <div class="ant-table-content">
            <table style="width: 1000px; min-width: 100%; table-layout: fixed;text-align:center;">
              <thead class="ant-table-thead">
                <tr>
                  <th class="ant-table-cell ant-table-cell-ellipsis">
                    <span>工单编号</span>
                  </th>
                  <th class="ant-table-cell ant-table-cell-ellipsis">
                    <span>产品名称</span>
                  </th>
                  <th class="ant-table-cell ant-table-cell-ellipsis">
                    <span>工序号</span>
                  </th>
                  <th class="ant-table-cell ant-table-cell-ellipsis">
                    <span>生产数量</span>
                  </th>
                  <th class="ant-table-cell ant-table-cell-ellipsis">
                    <span>上线时间</span>
                  </th>
                  <th class="ant-table-cell ant-table-cell-ellipsis" style="width:200px;">
                    <span>计划开工</span>
                  </th>
                  <th class="ant-table-cell ant-table-cell-ellipsis" style="width:200px;">
                    <span>计划完工</span>
                  </th>
                </tr>
              </thead>
              <tbody class="ant-table-tbody">
                <tr v-for="(item,index) in tableData" :key="index">
                  <td class="ant-table-cell ant-table-cell-ellipsis">
                    {{item.orderNumber}}
                  </td>
                  <td class="ant-table-cell ant-table-cell-ellipsis">
                    {{item.productName}}
                  </td>
                  <td class="ant-table-cell ant-table-cell-ellipsis">
                    {{item.productCode}}
                  </td>
                  <td class="ant-table-cell ant-table-cell-ellipsis">
                    {{item.quantity}}
                  </td>
                  <td class="ant-table-cell ant-table-cell-ellipsis">
                    {{item.schedulingTime}}
                  </td>
                  <td class="ant-table-cell ant-table-cell-ellipsis">
                    {{item.startTime}}
                  </td>
                  <td class="ant-table-cell ant-table-cell-ellipsis">
                    {{item.endTime}}
                  </td>
                </tr>
              </tbody>
            </table>
          </div> -->
          </div>

          <a-empty style="position: absolute;top: 50%;left: 45%;" v-else />
        </div>

      </div>
    </div>
    <!-- 右键菜单 -->
    <!-- 	<div id="contextmenu" v-show="false" class="menu">
			<div class="contextmenu__item">查看</div>
			<div class="contextmenu__item" @click="onEditBlock(editBlock, editRow)">修改</div>
			<div class="contextmenu__item" @click="onDeleteBlock(editBlock)">删除</div>
		</div> -->



    <!-- 编辑窗口 -->
    <!-- <el-dialog title="编辑时间块" :visible.sync="isEditBlock">
			<el-form v-if="editBlock" :model="editBlock" label-width="120px">
				<el-form-item label="名称"><el-input v-model="editBlock.projectName"
						autocomplete="off"></el-input></el-form-item>
				<el-form-item label="开始时间">
					<el-date-picker @change="onChangeStartTime" v-model="editBlock.startTime" type="datetime"
						placeholder="选择日期时间"></el-date-picker>
				</el-form-item>
				<el-form-item label="时间长度">
					<el-input-number v-model="editBlock.timeDiff" @change="onChangeStartTime" :min="1" :max="100"
						label="时间长度"></el-input-number>
				</el-form-item>
				<el-form-item label="结束时间"><el-date-picker readonly v-model="editBlock.endTime" type="datetime"
						placeholder="选择日期时间"></el-date-picker></el-form-item>
			</el-form>
			    <div slot="footer" class="dialog-footer">
				<el-button @click="onEditCancel()">取 消</el-button>
				<el-button type="primary" @click="onEditSave()">确 定</el-button>
			</div>
		</el-dialog> -->
  </div>
</template>

<script>
  import GanttRow from '/@/components/gantt-v/gantt-row.vue';
  import GanttBlock from '/@/components/gantt-v/gantt-block.vue';
  import GanttTimeBlock from '/@/components/gantt-v/gantt-time-block.vue';
  import ganttMix from '/@/components/gantt-v/gantt-mix.js';
  import ganttHisMix from '/@/components/gantt-v/gantt-his-mix.js';

  //import airPlaneData from '/@/views/fake-data/airPlaneData.js'; 
  import {
    defHttp
  } from '/@/utils/http/axios';
  //注册model
  import {
    useModal
  } from '/@/components/Modal';
  const [{
    openModal
  }] = useModal();
  export default {
    name: 'assemblyPlan-gantt',
    props: {
      searchParams: {
        type: Object,
        default: {}
      }
    },
    components: {
      GanttBlock,
      GanttRow,
      GanttTimeBlock
    },
    mixins: [ganttMix, ganttHisMix],
    data() {
      return {
        tableData: [],
        tableList: [],
        // 用right 的滚动，控制aside-left的滚动
        transFormYValue: 0,
        // 用right 的滚动，控制head-left的滚动
        transFormXValue: 0,
        // 飞机的数据，用于渲染左侧边
        ganttData: [],
        // 选择的时间区间
        choiceTime: [new Date('2023-04-01 00:00:00'), new Date('2023-04-30 00:00:00')],
        defaultTop: 4,
        nowSuck: -1,
        // X轴移动距离
        moveX: 0,
        // Y轴移动距离
        moveY: 0,

        // 是否显示编辑弹出框
        isEditBlock: false,
        // 编辑内容
        editBlock: null,
        // 编辑行
        editRow: null,
        // 数据列表key名字
        listKey: 'list',
        //右键菜单
        menuVisible: false,
      };
    },
    provide() {
      return {
        page: this
      };
    },
    computed: {
      // 通过选择的时间区间，得到这区间之间的数组
      choiceTimeArr() {
        const timeArr = [];
        // 时间戳毫秒为单位
        // 尾时间-首时间 算出头尾的时间戳差  再换算成天单位       毫秒->分->时->天
        const diffDays = (this.choiceTime[1].getTime() - this.choiceTime[0].getTime()) / 1000 / 60 /
          60 / 24;
        // 一天的时间戳
        const oneDayMs = 24 * 60 * 60 * 1000;
        // 差了多少天就便利多少天 首时间+当前便利的天数的毫秒数
        for (let i = 0; i < diffDays + 1; i++) {
          // 时间戳来一个相加，得到的就是时间数组
          timeArr.push(new Date(this.choiceTime[0].getTime() + i * oneDayMs));
        }

        // console.log(diffDays, oneDayMs, timeArr);
        return timeArr;
      },
    },
    created() {
      //this.tableList = this.tableData;
    },
    watch: {},
    methods: {
      // 获取列表
      getList() {
        // 处理表格搜索参数
        let tempSearchParams = {
          createdDateStart: this.searchParams.createdDate ? this.searchParams.createdDate[0] : '',
          createdDateEnd: this.searchParams.createdDate ? this.searchParams.createdDate[1] : '',
          plannedStartDateStart: this.searchParams.plannedStartDate ? this.searchParams
            .plannedStartDate[0] : '',
          plannedStartDateEnd: this.searchParams.plannedStartDate ? this.searchParams
            .plannedStartDate[1] : '',
          releasedDateStart: this.searchParams.releasedDate ? this.searchParams.releasedDate[0] :
            '',
          releasedDateEnd: this.searchParams.releasedDate ? this.searchParams.releasedDate[1] :
            '',
          moNo: this.searchParams.moNo,
          workCenterName: this.searchParams.workCenterName,
          productionOrderStateName: this.searchParams.productionOrderStateName,
          partCode: this.searchParams.partCode,
          pageNo: 1,
          pageSize: 10
        };
        let thisVW = this;
        defHttp.get({
          url: '/ps/productTemp/zzList',
          params: tempSearchParams
        }).then((res) => {
          if (res.records.length > 0) {
            let dateList = [];
            res.records.forEach(item => {
              dateList.push(new Date(item.plannedStartDate).getTime());
              // 结束时间为开始时间后的八小时  混入的方法是使用planStartTime和planEndTime去界定甘特图位置
              item.planStartTime = item.plannedStartDate;
              item.planEndTime = new Date(item.plannedStartDate).getTime() + 8 * 60 * 60 * 1000;
              // 混入处理时  方法采用的是projectName  故将数据中添加个projectName 避免报错
              item.projectName = item.partName;
              dateList.push(new Date(item.plannedStartDate).getTime() + 8 * 60 * 60 * 1000);
            })
            thisVW.compareDate(dateList);
            //status重新赋值									
            thisVW.ganttData = res.records;
          } else thisVW.ganttData = [];
          thisVW.$forceUpdate();
        });
      },
      // 比较时间大小
      compareDate(list) {
        let planDate = [];
        let max = Math.max(...list);
        let min = Math.min(...list);
        this.choiceTime = [new Date(min), new Date(max)];
      },
      // 滚动事件
      getScrollEvent() {
        const rightDom = this.$refs.contentGrid;
        rightDom.addEventListener('scroll', e => {
          const scrollLeft = e.target.scrollLeft;
          const scrollTop = e.target.scrollTop;
          this.transFormYValue = scrollTop;
          this.transFormXValue = scrollLeft;
        });

        const leftDom = this.$refs.left;
        leftDom.addEventListener('mousewheel', e => {
          const wheelValue = e.deltaY;
          rightDom.scrollTop += wheelValue;
        });
      },

      /**
       * 当对于这个时间块按下的时候
       * @param e 时间块的 event 事件
       * @param blockId 时间块的ID
       * @param rowIndex 该条线的id
       */
      onMouseDown(e, blockId, rowIndex) {
        // 删除模式下不处理拖动事件
        if (this.isDeleteMode) {
          return;
        }
        this.moveX = 0;
        this.moveY = 0;

        // 用box 移动，不采用 Doucment
        const box = this.$refs.box;
        const dom = e.target;
        // 算出鼠标相对元素的位置
        const disX = e.clientX - dom.offsetLeft;
        const disY = e.clientY - dom.offsetTop;

        // 当点击下来的时候 nowSuck 其实等于的就是当前index
        this.nowSuck = rowIndex;

        // 让本来拥有手掌样式的class取消
        dom.classList.remove('gantt-grab');
        // 让整个box 鼠标都是抓住
        box.classList.add('gantt-grabbing');

        // 如果事件绑定在 dom上，那么一旦鼠标移动过快就会脱离掌控
        box.onmousemove = ee => {
          // 获得当前受到拖拽的div 用于计算suck 所谓拖引的行数
          const top = parseInt(dom.style.top);
          // 四舍五入 获得磁性吸附激活的值 (索引值)  60是block的height 10是时间块距离block的top  suck 可以当作row的索引
          let suck = Math.round((top - 10) / 60) + rowIndex;

          // suck的边界值设置
          if (suck < 0) {
            suck = 0;
          } else if (suck > this.ganttData.length - 1) {
            suck = this.ganttData.length - 1;
          }

          // suck 行样式变化
          this.nowSuck = suck;

          // 移动事件
          this.onMouseMove(ee, disX, disY, dom);
        };
        // 不管在哪里，鼠标松开的时候，清空事件 所以对于这个 “不管在哪里，使用了window”
        window.onmouseup = () => {

          // 鼠标松开了，让时间块恢复手掌样式
          dom.classList.add('gantt-grab');
          // 整个box 不在抓住了，变成箭头鼠标
          box.classList.remove('gantt-grabbing');
          // 当移动距离小于5时,不做移动处理
          //console.log('移动距离:', this.moveX, this.moveY);
          // if (this.moveX < 1 && this.moveY < 1 && this.moveX > -1 && this.moveY > -1) {
          //   console.log('无效移动');
          //   box.onmousemove = null;
          //   window.onmouseup = null;
          //   this.nowSuck = -1;
          //   return;
          // }

          
          // 保存操作日志
          this._addHisList(this.ganttData);
          // 松开鼠标的时候 清空
          box.onmousemove = null;
          window.onmouseup = null;
          
          // 坐标定位 磁性吸附 永远的10px   不知道为啥动态绑定的元素也会受到以前元素的影响，可能是 for 中 index带来的影响
          dom.style.top = this.defaultTop + 'px';
          return;

          const index = this.ganttData[rowIndex].findIndex(item => {
            return item.id === blockId;
          });
          const oldTimeBlock = this.ganttData[rowIndex][index];
          // let timeId = oldTimeBlock.id;

          // startTime 与 endTime 用于数据重新替换  上面css已经经过计算 15px为1小时
          const startTime = new Date(this.choiceTime[0].getTime() + (parseInt(dom.style.left) *
            3600000) / 15);
          const endTime = new Date(this._getTime(startTime) + (parseInt(dom.style.width) *
            3600000) / 15);
          // console.log(startTime, endTime, dom.style.width, parseInt(dom.style.left) * 60 * 1000);
          const suck = this.nowSuck;

          // 加入新数据
          const data = oldTimeBlock;
          //时间格式化
          let sTime = this.changeTime(startTime);
          let eTime = this.changeTime(endTime);
          // 更新开始时间和结束时间
          data.startTime = sTime;
          data.endTime = eTime;
          //this.$set(data, 'startTime', startTime);
          //this.$set(data, 'endTime', endTime);
          // 修改时间块的topParentId
          //data.topParentId = this.ganttData[suck].id;
          //this.$set(data, 'topParentId', this.ganttData[suck].id);
          /**
           * 本来dom元素磁性吸附是打算用document.appendChild() 方式来做的，但是对于vue来说 for出来的子元素就算变了位置，其index也不属于新的row
           */
          // 老数据 删除
          this.ganttData[rowIndex].splice(index, 1);

          // 新数据加入
          this.ganttData[suck].push(data);

          // 坐标定位 磁性吸附 永远的10px   不知道为啥动态绑定的元素也会受到以前元素的影响，可能是 for 中 index带来的影响
          dom.style.top = this.defaultTop + 'px';

          // 松开鼠标的时候 清空
          box.onmousemove = null;
          window.onmouseup = null;

          // 需要重新计算吸附位置,以及整行重新排列
          this.$nextTick(() => {
            this._recalcRowTimes(data, this.ganttData[suck]);
          });



          // 将当前row 清空
          this.nowSuck = -1;
          // 改变位置后回调事件
          this.afterChangePosition(data, this.ganttData[rowIndex].id, this.ganttData[suck].id);
        };
      },

      // 时间块点击
      onClicked(times) {
        this.getPlansDayOneDetalis(times.topParentId);
      },

      /**
       * 鼠标移动的时候，前置条件鼠标按下
       * @param e 时间块的 event 事件
       * @param disX x轴
       * @param disY y轴
       * @param targetDom 时间块的dom 其实可以直接 e.target 获取
       */
      onMouseMove(e, disX, disY, targetDom) {
        // 用鼠标的位置减去鼠标相对元素的位置，得到元素的位置
        let left = e.clientX - disX;
        const top = e.clientY - disY;
        this.moveX = left;
        this.moveY = top;

        // 移动位置不能小于零(开始时间)
        if (left < 0) {
          left = 0;
        }

        //拖动时间块关闭右键菜单
        this.menuVisible = false;

        targetDom.style.left = left + 'px';
        targetDom.style.top = top + 'px';
      },
      /**
       * 时间块位置变化后回调事件
       * @param data 时间块的值 包括时间块id startTime endTime
       * @param rowOId 时间块原来所在的那个飞机id (一条横线)
       * @param rowNId 时间块新的所在的那个飞机id
       */
      afterChangePosition(data, rowOId, rowNId) {
        //保存数据
        this.savePlansDayDetalis(data);
      },

      save() {
        console.log(JSON.stringify(this.ganttData));
      },

      // 删除时间块,需要传入时间块信息和序号
      onDeleteBlock(block) {
        // 保存操作日志
        this._addHisList(this.ganttData);
        // const row = this.ganttData[rowIndex] /
        // row[this.listKey].splice(index, 1)
        this.$set(block, 'isValidate', '0');
      },

      onRightClick(event, row, block) {
        //编辑需要把时间长度先计算好
        block.timeDiff = (block.endTime - block.startTime) / 3600000;
        this.editRow = row;
        this.editBlock = block;

        this.menuVisible = false; // 先把模态框关死，目的是 第二次或者第n次右键鼠标的时候 它默认的是true
        this.menuVisible = true; // 显示模态窗口，跳出自定义菜单栏
        event.preventDefault(); //关闭浏览器右键默认事件
        this.CurrentRow = row;
        var menu = document.querySelector('.menu');
        this.styleMenu(menu);
      },

      cancelMouse() {
        // 取消鼠标监听事件 菜单栏
        this.menuVisible = false;
        document.removeEventListener('click', this.foo); // 关掉监听，
      },

      styleMenu(menu) {
        if (event.clientX > 1800) {
          menu.style.left = event.clientX - 100 + 'px';
        } else {
          menu.style.left = event.clientX + 1 + 'px';
        }
        document.addEventListener('click', this.cancelMouse); // 给整个document新增监听鼠标事件，点击任何位置执行foo方法
        if (event.clientY > 700) {
          menu.style.top = event.clientY - 30 + 'px';
        } else {
          menu.style.top = event.clientY - 10 + 'px';
        }
      },

      // 开始编辑时间块,需要传入时间块和本行列表
      onEditBlock() {
        this.editBlock = JSON.parse(JSON.stringify(this.editBlock));
        this.isEditBlock = true;
      },

      onChangeStartTime(event) {
        console.log('onChangeStartTime:', event);
        let startTime = this._getTime(this.editBlock.startTime);
        this._updateEndTimeByDiff(this.editBlock, startTime);
      },

      // 保存数据
      onEditSave() {
        this.isEditBlock = false;
        console.log(this.editRow, this.editBlock);

        const index = this.editRow.findIndex(item => {
          return item.id === this.editBlock.id;
        });
        if (index >= 0) {
          // 保存操作日志
          this._addHisList(this.ganttData);
          this.$set(this.editRow, index, this.editBlock);
          // 需要重新计算吸附位置,以及整行重新排列
          this.$nextTick(() => {
            this._recalcRowTimes(this.editBlock, this.editRow);
          });
        }
      },

      // 取消保存
      onEditCancel() {
        this.isEditBlock = false;
      },
      //根据计划id获取全部数据
      getPlansDayAllDetalis() {
        let thisVW = this;
        defHttp.post({
          url: '/ps/psProductionArrangementPlansDayDetalis/all',
          params: {
            // id: '1'
            // createTime : this.changeTime(new Date())
            createTime: '2023-04-01 00:00:00'
          }
        }).then((res) => {
          if (res && res.length > 0) {
            //status重新赋值									
            for (let i = 0; i < res.length; i++) {
              let dat = res[i].list;
              if (dat != null && dat.length > 0) {
                for (let j = 0; j < dat.length; j++) {
                  dat[j].status = Math.floor(Math.random() * 4);
                }
              }
            }
            thisVW.ganttData = res;
            console.log(res);
          }
        });
      },
      //点击某个甘特图单元格获取数据
      getPlansDayOneDetalis(id) {
        let thisVW = this;
        let i = Math.floor(Math.random() * 10);
        thisVW.tableData = thisVW.ganttData[i]["list"];
        /*  console.log("===点击某个甘特图单元格获取数据==");
			  defHttp.get({ url: '/ps/psProductionArrangementPlansDayDetalis/queryById', params: { id: id } }).then((res) => {
				console.log("===res=="+res);
				if (res && res.length > 0) {									
					thisVW.tableData = res; 
					console.log(res);	
				}
             });  */
      },
      //保存移动的甘特图
      savePlansDayDetalis(data) {
        defHttp.post({
          url: '/ps/psProductionArrangementPlansDayDetalis/change',
          params: data
        }).then((res) => {
          console.log(res);
        }).catch(err => {
          console.log(err);
        });
      },
      //双击事件
      onDbClicked() {
        alert("===双击事件===");
        /* openModal(true, {
        	isDetail:true,
        	showFooter: false,
        }); */
      },

      //将中国标准时间格式化
      changeTime(tm) {
        let date = new Date(tm);
        let y = date.getFullYear();
        let m = date.getMonth() + 1;
        m = m < 10 ? ('0' + m) : m;
        let d = date.getDate();
        d = d < 10 ? ('0' + d) : d;
        let h = date.getHours();
        h = h < 10 ? ('0' + h) : h;
        let minutes = date.getMinutes();
        minutes = minutes < 10 ? ('0' + minutes) : minutes;
        let s = date.getSeconds();
        s = s < 10 ? ('0' + s) : s;
        return y + '-' + m + '-' + d + ' ' + h + ':' + minutes + ':' + s;
      }

    },
    mounted() {
      this.getList();
      this.getScrollEvent();
      //排产计划当天详情
      // this.getPlansDayAllDetalis();
    }
  };

</script>

<style scoped lang="scss">
  @import '/@/components/gantt-v/css/gant-v.scss';

  .ant-table-tbody>tr>td {
    border: 1px solid #ccc;
  }

  .ant-table-thead>tr>th {
    border: 1px solid #ccc;
    text-align: center;
    font-weight: 600;
  }

  .gantt-grab-no {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .contextmenu__item {
    display: block;
    line-height: 34px;
    text-align: center;
  }

  .contextmenu__item:not(:last-child) {
    border-bottom: 1px solid rgba(0, 0, 0, 0.1);
  }

  .menu {
    position: absolute;
    background-color: #fff;
    width: 100px;
    /*height: 106px;*/
    font-size: 12px;
    color: #444040;
    border-radius: 4px;
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
    border-radius: 3px;
    border: 1px solid rgba(0, 0, 0, 0.15);
    box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
    white-space: nowrap;
    z-index: 1000;
  }

  .contextmenu__item:hover {
    cursor: pointer;
    background: #66b1ff;
    border-color: #66b1ff;
    color: #fff;
  }

</style>
